package yunjiao.javatutorials.guava.concurrent.log;

import yunjiao.javatutorials.guava.concurrent.ForwardingLock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * 强的 LoggingLock，支持 Condition 的日志记录
 *
 * @author yangyunjiao
 */
public class EnhancedLoggingLock extends ForwardingLock {
    private final Lock delegate;
    private final String name;

    public EnhancedLoggingLock(Lock delegate, String name) {
        this.delegate = delegate;
        this.name = name;
    }

    @Override
    protected Lock delegate() {
        return delegate;
    }

    @Override
    public void lock() {
        System.out.println("[" + name + "] 尝试获取锁...");
        long startTime = System.currentTimeMillis();
        super.lock();
        long endTime = System.currentTimeMillis();
        System.out.println("[" + name + "] 锁获取成功，耗时 " + (endTime - startTime) + "ms");
    }

    @Override
    public void unlock() {
        System.out.println("[" + name + "] 释放锁");
        super.unlock();
    }

    @Override
    public Condition newCondition() {
        System.out.println("[" + name + "] 创建新条件变量");
        return new LoggingCondition(super.newCondition(), name + "-Condition");
    }

    /**
     * 带日志记录的 Condition 包装器
     */
    private static class LoggingCondition implements Condition {
        private final Condition delegate;
        private final String name;

        public LoggingCondition(Condition delegate, String name) {
            this.delegate = delegate;
            this.name = name;
        }

        @Override
        public void await() throws InterruptedException {
            System.out.println("[" + name + "] 开始等待...");
            long startTime = System.currentTimeMillis();
            delegate.await();
            long endTime = System.currentTimeMillis();
            System.out.println("[" + name + "] 等待结束，耗时 " + (endTime - startTime) + "ms");
        }

        @Override
        public boolean await(long time, TimeUnit unit) throws InterruptedException {
            System.out.println("[" + name + "] 开始等待，超时: " + time + " " + unit);
            long startTime = System.currentTimeMillis();
            boolean result = delegate.await(time, unit);
            long endTime = System.currentTimeMillis();
            System.out.println("[" + name + "] 等待结束，结果: " + result + "，耗时 " + (endTime - startTime) + "ms");
            return result;
        }

        @Override
        public long awaitNanos(long nanosTimeout) throws InterruptedException {
            System.out.println("[" + name + "] 开始等待，超时: " + nanosTimeout + " 纳秒");
            long startTime = System.nanoTime();
            long remaining = delegate.awaitNanos(nanosTimeout);
            long endTime = System.nanoTime();
            System.out.println("[" + name + "] 等待结束，剩余时间: " + remaining + " 纳秒，总耗时 " + (endTime - startTime) + " 纳秒");
            return remaining;
        }

        @Override
        public void signal() {
            System.out.println("[" + name + "] 发送信号");
            delegate.signal();
        }

        @Override
        public void signalAll() {
            System.out.println("[" + name + "] 广播信号");
            delegate.signalAll();
        }

        // 实现其他 Condition 方法...
        @Override
        public void awaitUninterruptibly() {
            System.out.println("[" + name + "] 开始不可中断等待");
            delegate.awaitUninterruptibly();
            System.out.println("[" + name + "] 不可中断等待结束");
        }

        @Override
        public boolean awaitUntil(java.util.Date deadline) throws InterruptedException {
            System.out.println("[" + name + "] 开始等待直到: " + deadline);
            boolean result = delegate.awaitUntil(deadline);
            System.out.println("[" + name + "] 等待直到结束，结果: " + result);
            return result;
        }
    }
}
